home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol06 / 03 / wintro6 / stock.c < prev    next >
C/C++ Source or Header  |  1991-05-01  |  28KB  |  908 lines

  1. /*
  2.   Microsoft Systems Journal Stock Application
  3.   Written by Marc Adler
  4.              Magma Systems
  5.              15 Bodwell Terrace
  6.              Millburn, New Jersey  07041
  7.  
  8.   This is for the fifth article. It is the basic skeleton of our
  9.   application. We add graphics to the code.
  10. */
  11.  
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include "windows.h"
  15. #include "stock.h"
  16.  
  17.  
  18. HANDLE hThisInstance;         /* Program instance handle */
  19. HWND hWndMain      = NULL;    /* Handle to main window   */
  20. HWND hwndMDIClient = NULL;    /* Handle to MDI client    */
  21. HWND hWndActive    = NULL;    /* Handle of the active MDI child */
  22. HWND hWndStatus    = NULL;    /* Window for status mesages */
  23.  
  24. HANDLE hCurrStockInfo;
  25. HANDLE hAccelTable;
  26.  
  27. WORD   iLastCommand;
  28.  
  29.  
  30. /********************************************************************/
  31. /*                                                                  */
  32. /* Function : WinMain()                                             */
  33. /*                                                                  */
  34. /* Purpose  : Entry point for our program. Calls the initialization */
  35. /*            routines, creates the main window, and goes into the  */
  36. /*            standard windows message loop (with MDI calls).       */
  37. /*                                                                  */
  38. /* Returns  : 0                                                     */
  39. /*                                                                  */
  40. /********************************************************************/
  41. int NEAR PASCAL WinMain(hInstance,hPrevInstance,lpszCmdLine,nCmdShow)
  42.   HANDLE hInstance;
  43.   HANDLE hPrevInstance;
  44.   LPSTR  lpszCmdLine;
  45.   int    nCmdShow;
  46. {
  47.   MSG msg;
  48.  
  49.   /*
  50.     Save the handle to this inctance.
  51.   */
  52.   hThisInstance = hInstance;
  53.  
  54.   /* 
  55.     If this is the first instance of the app, register window classes.
  56.   */
  57.   if (!hPrevInstance)
  58.   {
  59.     if (!InitializeApplication())
  60.     {
  61.       MessageBeep(0);
  62.       return FALSE;
  63.     }
  64.   }
  65.  
  66.   /* 
  67.     Perform the initialization for this particular instance...
  68.   */
  69.   if (!InitializeInstance(lpszCmdLine, nCmdShow))
  70.   {
  71.     return FALSE;
  72.   }
  73.  
  74.  
  75.   /*
  76.     The main message loop...
  77.   */
  78.   while (GetMessage(&msg, (HWND) NULL, 0, 0))
  79.   {
  80.     /* If a keyboard message is for the MDI , let the MDI client
  81.      * take care of it.  Otherwise, check to see if it's a normal
  82.      * accelerator key (like F3 = find next).  Otherwise, just handle
  83.      * the message as usual.
  84.      */
  85.     if (!TranslateMDISysAccel(hwndMDIClient, &msg) && 
  86.         !TranslateAccelerator(hWndMain, hAccelTable, &msg))
  87.     {
  88.       TranslateMessage(&msg);
  89.       DispatchMessage(&msg);
  90.     }
  91.   }
  92.  
  93.   return msg.wParam;
  94. }
  95.  
  96.  
  97. /********************************************************************/
  98. /*                                                                  */
  99. /* Function : InitializeApplication()                               */
  100. /*                                                                  */
  101. /* Purpose  : Takes care of the per-application initialization. This*/
  102. /*            means registering all of our classes.                 */
  103. /*                                                                  */
  104. /* Returns  : FALSE if a class could not be registered, else TRUE.  */
  105. /*                                                                  */
  106. /********************************************************************/
  107. BOOL FAR PASCAL InitializeApplication(VOID)
  108. {
  109.   WNDCLASS wc;
  110.  
  111.   /*
  112.     Register the main window class
  113.   */
  114.   wc.style         = CS_VREDRAW | CS_HREDRAW;
  115.   wc.lpfnWndProc   = MainWndProc;
  116.   wc.cbClsExtra    = 0;
  117.   wc.cbWndExtra    = 0;
  118.   wc.hInstance     = hThisInstance;
  119.   wc.hIcon         = LoadIcon(hThisInstance,
  120.                               MAKEINTRESOURCE(ID_STOCK));
  121.   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  122.   wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  123.   wc.lpszMenuName  = "StockMenu";
  124.   wc.lpszClassName = "StockMainWindow";
  125.   if (!RegisterClass(&wc))
  126.     return FALSE;
  127.  
  128.   /* Register the MDI child class */
  129.   wc.lpfnWndProc   = GraphWndProc;
  130.   wc.hIcon         = LoadIcon(hThisInstance,
  131.                               MAKEINTRESOURCE(ID_GRAPH));
  132.   wc.lpszMenuName  = NULL;
  133.   wc.cbWndExtra    = CBWNDEXTRA;
  134.   wc.lpszClassName = "GraphWindow";
  135.   if (!RegisterClass(&wc))
  136.     return FALSE;
  137.  
  138.   wc.style         = CS_VREDRAW | CS_HREDRAW;
  139.   wc.lpfnWndProc   = StatusWndProc;
  140.   wc.cbClsExtra    = 0;
  141.   wc.cbWndExtra    = 0;
  142.   wc.hInstance     = hThisInstance;
  143.   wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  144.   wc.lpszMenuName  = NULL;
  145.   wc.lpszClassName = "StockStatus";
  146.   if (!RegisterClass(&wc))
  147.     return FALSE;
  148.  
  149.   return TRUE;
  150. }
  151.  
  152.  
  153. /********************************************************************/
  154. /*                                                                  */
  155. /* Function : InitializeInstance()                                  */
  156. /*                                                                  */
  157. /* Purpose  : Performs per-instance initialization. This means      */
  158. /*            creating the main window (which in turn creates the   */
  159. /*            MDI client) and                                       */
  160. /*            loading in the accelerator table.                     */
  161. /*                                                                  */
  162. /* Returns  : FALSE if it couldn't do the init, TRUE if successful. */
  163. /*                                                                  */
  164. /********************************************************************/
  165. BOOL FAR PASCAL InitializeInstance(LPSTR lpCmdLine, WORD nCmdShow)
  166. {
  167.   /* 
  168.     Create the frame
  169.   */
  170.   hWndMain = CreateWindow("StockMainWindow",
  171.                           "MSJ Stock Application",
  172.                           WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  173.                           CW_USEDEFAULT, 0,
  174.                           CW_USEDEFAULT, 0,
  175.                           (HWND) NULL,
  176.                           (HMENU) NULL,
  177.                           hThisInstance,
  178.                           (LPSTR) NULL);
  179.   if (!hWndMain)
  180.     return FALSE;
  181.  
  182.   /* 
  183.     The MDI client should have been created in response to WM_CREATE
  184.     message for the frame window.
  185.   */
  186.   CreateMDIClient(hWndMain);
  187.   if (!hwndMDIClient)
  188.     return FALSE;
  189.  
  190.   /*
  191.     Load the accelerators in
  192.   */
  193.   hAccelTable = LoadAccelerators(hThisInstance, 
  194.                                 (LPSTR) "StockAccelerators");
  195.  
  196.   /* 
  197.     Display the main window
  198.   */
  199.   ShowWindow(hWndMain, nCmdShow);
  200.   UpdateWindow(hWndMain);
  201.  
  202.   return TRUE;
  203. }
  204.  
  205.  
  206. /********************************************************************/
  207. /*                                                                  */
  208. /* Function : MainWndProc()                                         */
  209. /*                                                                  */
  210. /* Purpose  : Window proc for the main window.                      */
  211. /*                                                                  */
  212. /********************************************************************/
  213. LONG FAR PASCAL MainWndProc(hWnd, msg, wParam, lParam)
  214.   HWND hWnd;
  215.   WORD msg;
  216.   WORD wParam;
  217.   LONG lParam;
  218. {
  219.   int         rc;
  220.   HDC         hDC;
  221.   PAINTSTRUCT ps;
  222.   FARPROC     lpfn;
  223.   HANDLE      hStockInfo;
  224.   LPSTOCKINFO lpStockInfo;
  225.  
  226.   char        szMsg[80];
  227.   RECT        rClient;
  228.   int         i;
  229.  
  230.   static HWND ahwndSubMenus[16];
  231.  
  232.  
  233.   switch (msg)
  234.   {
  235.     case WM_CREATE:
  236.       /*
  237.         Create a status window at the bottom of the main window.
  238.       */
  239.       GetClientRect(hWnd, (LPRECT) &rClient);
  240.       hWndStatus = CreateWindow("StockStatus",
  241.                     NULL,
  242.                     WS_CHILD | WS_BORDER,
  243.                     rClient.left, rClient.bottom - Y_STATUSWINDOW,
  244.                     rClient.right - rClient.left, Y_STATUSWINDOW,
  245.                     hWnd,
  246.                     NULL, 
  247.                     hThisInstance,
  248.                     (LPSTR) 0L);
  249.       if (hWndStatus)
  250.         ShowWindow(hWndStatus, SW_SHOW);
  251.  
  252.       /*
  253.         We gather up the window handles of all of the sub menus.
  254.       */
  255.       for (i = 0;  (ahwndSubMenus[i] = GetSubMenu(GetMenu(hWnd),i));
  256.            i++)
  257.         ;
  258.  
  259.       break;
  260.  
  261.  
  262.     case WM_COMMAND :
  263.       switch (iLastCommand = wParam)
  264.       {
  265.         case ID_NEW   :
  266.         case ID_GRAPH_OPTIONS :
  267.           if (wParam == ID_NEW || hCurrStockInfo == NULL)
  268.           {
  269.             if ((hStockInfo = StockInfoAlloc()) == NULL)
  270.             {
  271.               MessageBox(hWnd,"No memory for stock info",NULL,MB_OK);
  272.               break;
  273.             }
  274.           }
  275.           else
  276.           {
  277.             hStockInfo = hCurrStockInfo;
  278.           }
  279.  
  280.           lpfn = MakeProcInstance((FARPROC) GraphOptionsDlgProc,
  281.                                    hThisInstance);
  282.           rc = DialogBoxParam(hThisInstance, "Graph", hWnd, lpfn,
  283.                               MAKELONG(hStockInfo,0));
  284.           FreeProcInstance(lpfn);
  285.  
  286.           if (rc == IDOK)
  287.           {
  288.             hCurrStockInfo = hStockInfo;
  289.           }
  290.           else
  291.           {
  292.             if (wParam == ID_NEW)
  293.               GlobalFree(hStockInfo);
  294.           }
  295.           break;
  296.  
  297.         case ID_OPEN  :
  298.           /*
  299.             Open up a stock file
  300.           */
  301.           lpfn = MakeProcInstance((FARPROC) OpenDlg, hThisInstance);
  302.           DialogBox(hThisInstance, "Open", hWnd, lpfn);
  303.           FreeProcInstance(lpfn);
  304.           break;
  305.  
  306.         case ID_SAVE  :
  307.           if (hCurrStockInfo)
  308.             StockFileSave(hCurrStockInfo);
  309.           break;
  310.  
  311.         case ID_CLOSE :
  312.           if (hWndActive)
  313.             SendMessage(hWndActive, WM_SYSCOMMAND, SC_CLOSE, 0L);
  314.           break;
  315.  
  316.         case ID_PRINT :
  317.           PrintFile();
  318.           break;
  319.  
  320.         case ID_EXIT  :
  321.           PostQuitMessage(0);
  322.           break;
  323.  
  324.  
  325.         /*
  326.           Add a new tick
  327.         */
  328.         case ID_TICK_ADD :
  329.           /*
  330.             Prompt the user for the new tick info
  331.           */
  332.           lpfn = MakeProcInstance(AddTickDlgProc, hThisInstance);
  333.           rc = DialogBoxParam(hThisInstance, "AddTick", hWnd, lpfn, -1L);
  334.           FreeProcInstance(lpfn);
  335.  
  336.           /*
  337.             See if the user chose OK...
  338.           */
  339.           if (rc == TRUE)
  340.           {
  341.             /*
  342.               If there is new tick information, update the graph for
  343.               the stock. We invalidate the entire MDI child window
  344.               for this stock and call UpdateWindow(). This, in turn,
  345.               sends a WM_PAINT message to the child window.
  346.             */
  347.             if ((lpStockInfo = (LPSTOCKINFO)
  348.                               GlobalLock(hCurrStockInfo)))
  349.             {
  350.               HWND h = lpStockInfo->hWnd;
  351.               GlobalUnlock(hCurrStockInfo);
  352.               InvalidateRect(h, (LPRECT) NULL, FALSE);
  353.               UpdateWindow(h);
  354.             }
  355.           }
  356.           break;
  357.  
  358.         case ID_TICK_CHANGE:
  359.           lpfn = MakeProcInstance((FARPROC) ChangeTickDlgProc,
  360.                                   hThisInstance);
  361.           rc = DialogBox(hThisInstance, "ChangeTickDlg", hWnd, lpfn);
  362.           FreeProcInstance(lpfn);
  363.           break;
  364.  
  365.         case ID_GRAPH_PRICE     :
  366.           break;
  367.         case ID_GRAPH_VOLUME    :
  368.           break;
  369.  
  370.         case ID_GRAPH_COLORS    :
  371.           lpfn = MakeProcInstance((FARPROC) GraphColorsDlgProc,
  372.                                   hThisInstance);
  373.           rc = DialogBox(hThisInstance, "Colors", hWnd, lpfn);
  374.           FreeProcInstance(lpfn);
  375.           break;
  376.  
  377.         case ID_GRAPH_FONTS     :
  378.           lpfn = MakeProcInstance((FARPROC) FontDlgProc,
  379.                                   hThisInstance);
  380.           rc = DialogBox(hThisInstance, "FontSizes", hWnd, lpfn);
  381.           FreeProcInstance(lpfn);
  382.           break;
  383.  
  384.         case ID_GRAPH_GRID_HORZ :
  385.           break;
  386.         case ID_GRAPH_GRID_VERT :
  387.           break;
  388.  
  389.         case ID_GRAPH_ISOTROPIC   :
  390.         case ID_GRAPH_ANISOTROPIC :
  391.           if (hCurrStockInfo && 
  392.              (lpStockInfo=(LPSTOCKINFO)GlobalLock(hCurrStockInfo)))
  393.           {
  394.             HWND h = lpStockInfo->hWnd;
  395.             lpStockInfo->graphAttrs.iMappingMode =
  396.                (wParam == ID_GRAPH_ISOTROPIC) ? MM_ISOTROPIC
  397.                                               : MM_ANISOTROPIC;
  398.             GlobalUnlock(hCurrStockInfo);
  399.             InvalidateRect(h, (LPRECT) NULL, FALSE);
  400.             UpdateWindow(h);
  401.  
  402.             if (wParam == ID_GRAPH_ISOTROPIC)
  403.             {
  404.               CheckMenuItem(GetMenu(hWnd), ID_GRAPH_ISOTROPIC, 
  405.                                     MF_BYCOMMAND | MF_CHECKED);
  406.               CheckMenuItem(GetMenu(hWnd), ID_GRAPH_ANISOTROPIC, 
  407.                                     MF_BYCOMMAND | MF_UNCHECKED);
  408.             }
  409.             else
  410.             {
  411.               CheckMenuItem(GetMenu(hWnd), ID_GRAPH_ISOTROPIC,
  412.                                     MF_BYCOMMAND | MF_UNCHECKED);
  413.               CheckMenuItem(GetMenu(hWnd), ID_GRAPH_ANISOTROPIC,
  414.                                     MF_BYCOMMAND | MF_CHECKED);
  415.             }
  416.           }
  417.  
  418.           break;
  419.  
  420.  
  421.         /*
  422.           MDI functions...
  423.         */
  424.         case ID_WINDOW_TILE     :
  425.           SendMessage(hwndMDIClient, WM_MDITILE, 0, 0L);
  426.           break;
  427.         case ID_WINDOW_CASCADE  :
  428.           SendMessage(hwndMDIClient, WM_MDICASCADE, 0, 0L);
  429.           break;
  430.         case ID_WINDOW_ICONS    :
  431.           SendMessage(hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  432.           break;
  433.  
  434.         case ID_WINDOW_CLOSEALL :
  435.         {
  436.           HWND hwndT;
  437.           ShowWindow(hwndMDIClient, SW_HIDE);
  438.           while ((hwndT = GetWindow(hwndMDIClient, GW_CHILD)))
  439.           {
  440.             /* Skip the icon title windows */
  441.             while (hwndT && GetWindow(hwndT, GW_OWNER))
  442.           hwndT = GetWindow(hwndT, GW_HWNDNEXT);
  443.             if (!hwndT)
  444.           break;
  445.             SendMessage(hwndMDIClient, WM_MDIDESTROY, hwndT, 0L);
  446.           }
  447.           ShowWindow(hwndMDIClient, SW_SHOW);
  448.           ShowWindow(hWndStatus, SW_SHOW);
  449.           break;
  450.         }
  451.  
  452.         case ID_ABOUT :
  453.           lpfn = MakeProcInstance(AboutDlgProc, hThisInstance);
  454.           rc = DialogBox(hThisInstance, MAKEINTRESOURCE(ID_ABOUT), 
  455.                          hWnd, lpfn);
  456.           FreeProcInstance(lpfn);
  457.           break;
  458.  
  459.         default :
  460.           /*
  461.             We might have chosen to change the focus to one of the
  462.             MDI children.
  463.           */
  464.           return DefFrameProc(hWnd,hwndMDIClient,msg,wParam,lParam);
  465.       }
  466.       break;
  467.  
  468.  
  469.     case WM_QUERYENDSESSION:
  470.       SendMessage(hWnd, WM_COMMAND, ID_WINDOW_CLOSEALL, 0L) ;
  471.       return (GetWindow(hwndMDIClient, GW_CHILD) == NULL);
  472.  
  473.     case WM_CLOSE:
  474.       SendMessage(hWnd, WM_COMMAND, ID_WINDOW_CLOSEALL, 0L) ;
  475.       if (GetWindow(hwndMDIClient, GW_CHILD) != NULL)
  476.       {
  477.         MessageBox(hWnd, "Found a child", "WM_CLOSE", MB_OK);
  478.         break;
  479.       }
  480.       DestroyWindow(hWnd);
  481.       break;
  482.  
  483.     case WM_DESTROY :
  484.       PostQuitMessage(0);
  485.       break;
  486.  
  487.  
  488.     case WM_MENUSELECT  :
  489.     {
  490.       WORD idMenu;
  491.       WORD iLen;
  492.  
  493.       /*
  494.         We trigger off of the WM_MENUSELECT message so that we
  495.         can print informative messages about each menu option.
  496.       */
  497.  
  498.       if (lParam & MF_POPUP)
  499.       {
  500.         /*
  501.           The handle of the popup menu is returned in wParam. Search
  502.           the array of sub-menu window handles in order to see which
  503.           submenu we are in.
  504.         */
  505.         for (idMenu = 0;
  506.              ahwndSubMenus[idMenu] && wParam!=ahwndSubMenus[idMenu];
  507.              idMenu++)
  508.           ;
  509.         if (!ahwndSubMenus[idMenu])
  510.           break;
  511.         idMenu++;  /* make it a 1-offset value */
  512.       }
  513.       else
  514.         /*
  515.           An actual menu item identifier is returned in wparam...
  516.         */
  517.         idMenu = wParam;
  518.  
  519.       /*
  520.         If lParam was <-1,0>, then the user dismissed the menu, so
  521.         we just want to erase the previous help text from the
  522.         status window. If not, then idMenu contains a valid menu or
  523.         submenu identifier. Load the corresponding string from
  524.         the string table, and print it.
  525.       */
  526.       if (LOWORD(lParam) == -1 && HIWORD(lParam) == 0  ||
  527.          ((iLen = LoadString(hThisInstance, idMenu, (LPSTR) szMsg,
  528.                              sizeof(szMsg))))
  529.          || iLen == 0)
  530.       {
  531.         HDC hDC = GetDC(hWndStatus);
  532.         HBRUSH hBrush, hOldBrush;
  533.  
  534.         /*
  535.           Use a white brush for erasing.
  536.         */
  537.         hBrush = CreateSolidBrush(0x00FFFFFF);
  538.         hOldBrush = SelectObject(hDC, hBrush);
  539.  
  540.         /*
  541.           Erase the previous menu help text, if any. Then display the
  542.           new help text.
  543.         */
  544.         GetClientRect(hWndStatus, (LPRECT) &rClient);
  545.         FillRect(hDC, &rClient, hBrush);
  546.         if (LOWORD(lParam) == -1 && HIWORD(lParam) == 0 || iLen == 0)
  547.           ;
  548.         else
  549.           TextOut(hDC, 0, 0, szMsg, iLen);
  550.  
  551.         /*
  552.           Restore the old brush.
  553.         */
  554.         SelectObject(hDC, hOldBrush);
  555.         DeleteObject(hBrush);
  556.         ReleaseDC(hWndStatus, hDC);
  557.       }
  558.       break;
  559.     }
  560.  
  561.  
  562.     case WM_SIZE :
  563.       /*
  564.         When the main window is resized, we want to move and resize
  565.         the status window so that it is always lying on the bottom.
  566.       */
  567.       if (hWndStatus)
  568.       {
  569.         GetClientRect(hWnd, (LPRECT) &rClient);
  570.         MoveWindow(hWndStatus, 
  571.                    rClient.left, rClient.bottom - Y_STATUSWINDOW,
  572.                    rClient.right - rClient.left, Y_STATUSWINDOW,
  573.                    TRUE);
  574.       }
  575.       /*
  576.         We need to call DefFrameProc, because it processes the
  577.         WM_SIZE messages too!
  578.       */
  579.       goto call_DFP;
  580.  
  581.  
  582.     default :
  583.       /*
  584.         Use DefFrameProc() instead of DefWindowProc() since there
  585.         are things that have to be handled differently because of
  586.         MDI
  587.       */
  588. call_DFP:
  589.       return DefFrameProc(hWnd, hwndMDIClient, msg, wParam, lParam);
  590.   }
  591.  
  592.  
  593.   return (LONG) TRUE;
  594. }
  595.  
  596.  
  597. VOID PASCAL CreateMDIClient(HWND hwndParent)
  598. {
  599.   CLIENTCREATESTRUCT ccs;
  600.   RECT               rClient;
  601.  
  602.   /* Find window menu where children will be listed */
  603.   ccs.hWindowMenu = GetSubMenu(GetMenu(hwndParent), 3);
  604.   ccs.idFirstChild = ID_WINDOW_CHILDREN;
  605.  
  606.   /* Create the MDI client filling the client area */
  607.   GetClientRect(hwndParent, (LPRECT) &rClient);
  608.   hwndMDIClient = CreateWindow("mdiclient",
  609.                                NULL,
  610.                                WS_CHILD | WS_CLIPCHILDREN | 
  611.                                WS_CLIPSIBLINGS,
  612.                                0,0,
  613.                                rClient.right,
  614.                                rClient.bottom-(Y_STATUSWINDOW*5),
  615.                                hwndParent,
  616.                                100,
  617.                                hThisInstance,
  618.                                (LPSTR) &ccs);
  619.   ShowWindow(hwndMDIClient, SW_SHOW);
  620. }
  621.  
  622.  
  623. /****************************************************************
  624.  *                                *
  625.  *  FUNCTION   : StatusWndProc ( hwnd, msg, wParam, lParam )    *
  626.  *                                *
  627.  *  PURPOSE    : Window Proc for the status window.        *
  628.  *                                *
  629.  ****************************************************************/
  630. LONG FAR PASCAL StatusWndProc(hWnd, msg, wParam, lParam)
  631.   HWND hWnd;
  632.   WORD msg;
  633.   WORD wParam;
  634.   LONG lParam;
  635. {
  636.   return DefWindowProc(hWnd, msg, wParam, lParam);
  637. }
  638.  
  639.  
  640. /****************************************************************
  641.  *                                *
  642.  *  FUNCTION   : AboutDlgProc ( hwnd, msg, wParam, lParam )    *
  643.  *                                *
  644.  *  PURPOSE    : Dialog function for the About MultiPad.. dialog*
  645.  *                                *
  646.  ****************************************************************/
  647. BOOL FAR PASCAL AboutDlgProc(hDlg, msg, wParam, lParam)
  648.   HWND hDlg;
  649.   WORD msg;
  650.   WORD wParam;
  651.   LONG lParam;
  652. {
  653.   switch (msg)
  654.   {
  655.     case WM_INITDIALOG:
  656.       /* nothing to initialize */
  657.       break;
  658.  
  659.     case WM_COMMAND:
  660.       switch (wParam)
  661.       {
  662.         case IDOK:
  663.           EndDialog(hDlg, 0);
  664.           break;
  665.  
  666.         default:
  667.           return FALSE;
  668.       }
  669.       break;
  670.  
  671.     default:
  672.       return FALSE;
  673.   }
  674.  
  675.   return TRUE;
  676. }
  677.  
  678.  
  679.  
  680. /********************************************************************/
  681. /*                                                                  */
  682. /* Function : GraphCreateWindow()                                   */
  683. /*                                                                  */
  684. /* Purpose  : Creates an MDI child window to hold a stock graph in. */
  685. /*                                                                  */
  686. /* Returns  : The handle of the created MDI child window.           */
  687. /*                                                                  */
  688. /********************************************************************/
  689. HWND PASCAL GraphCreateWindow(LPSTR lpName)
  690. {
  691.   HWND hWnd;
  692.   char sz[160];
  693.   MDICREATESTRUCT mcs;
  694.  
  695.   if (!lpName)
  696.   {
  697.     /* 
  698.       If the lpName parameter is NULL, load the "Untitled" string
  699.       from STRINGTABLE and set the title field of the MDI
  700.       CreateStruct.
  701.     */
  702.     strcpy(sz, "(Untitled)");
  703.     mcs.szTitle = (LPSTR) sz;
  704.   }
  705.   else
  706.   {
  707.     /* Title the window with the supplied filename */
  708.     AnsiUpper(lpName);
  709.     mcs.szTitle = lpName;
  710.   }
  711.  
  712.   mcs.szClass = "GraphWindow";
  713.   mcs.hOwner  = hThisInstance;
  714.  
  715.   /* Use the default size for the window */
  716.   mcs.x = mcs.cx = CW_USEDEFAULT;
  717.   mcs.y = mcs.cy = CW_USEDEFAULT;
  718.  
  719.   /* Set the style DWORD of the window to default */
  720.   mcs.style = 0L;
  721.  
  722.   /* tell the MDI Client to create the child */
  723.   hWnd = (WORD) SendMessage(hwndMDIClient,
  724.                 WM_MDICREATE,
  725.                 0,
  726.                 (LONG) (LPMDICREATESTRUCT) &mcs);
  727.   return hWnd;
  728. }
  729.  
  730.  
  731. /*******************************************************************/
  732. /*                                                                 */
  733. /* Function : GraphWndProc()                                       */
  734. /*                                                                 */
  735. /* Purpose  : Window proc for the stock MDI child windows.         */
  736. /*                                                                 */
  737. /* Returns  :                                                      */
  738. /*                                                                 */
  739. /*******************************************************************/
  740. LONG FAR PASCAL GraphWndProc(hWnd, msg, wParam, lParam)
  741.   HWND hWnd;
  742.   WORD msg;
  743.   WORD wParam;
  744.   LONG lParam;
  745. {
  746.   HANDLE      hStockInfo;
  747.   LPSTOCKINFO lpStockInfo;
  748.  
  749.   switch (msg)
  750.   {
  751.     case WM_CREATE   :
  752.       SetWindowWord(hWnd, 0, NULL);
  753.       break;
  754.  
  755. #if 0
  756.     case WM_NCCALCSIZE :
  757.     {
  758.       LPRECT lpRect = (LPRECT) lParam;
  759.       RECT   rStatus;
  760.       RECT   rDummy;
  761.  
  762.       DefMDIChildProc(hWnd, msg, wParam, lParam);
  763.       GetWindowRect(hWndStatus, (LPRECT) &rStatus);
  764.       if (IntersectRect((LPRECT) &rDummy, lpRect, (LPRECT) &rStatus))
  765.       {
  766.         lpRect->bottom = rStatus.top-GetSystemMetrics(SM_CYFRAME)-1;
  767.       }
  768.       return TRUE;
  769.     }
  770. #endif
  771.  
  772.     case WM_SIZE :
  773.     {
  774.       RECT   rStatus;
  775.       RECT   rDummy;
  776.       RECT   rWindow;
  777.  
  778.       DefMDIChildProc(hWnd, msg, wParam, lParam);
  779.       GetWindowRect(hWnd, (LPRECT) &rWindow);
  780.       GetWindowRect(hWndStatus, (LPRECT) &rStatus);
  781.       if (IntersectRect((LPRECT) &rDummy, (LPRECT) &rWindow,
  782.                         (LPRECT) &rStatus))
  783.       {
  784.         rWindow.bottom = rStatus.top - 1;
  785.         if (wParam == SIZEICONIC)
  786.         {
  787.            SetWindowPos(hWnd, NULL,
  788.                         rWindow.left, 
  789.                         rWindow.top - (rStatus.bottom-rStatus.top),
  790.                         0,
  791.                         0,
  792.                         SWP_NOSIZE | SWP_NOREDRAW | SWP_NOZORDER);
  793.         }
  794.         else
  795.           SetWindowPos(hWnd, NULL,
  796.                        0, 0, 
  797.                        rWindow.right - rWindow.left + 1,
  798.                        rWindow.bottom - rWindow.top + 1,
  799.                        SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
  800.         InvalidateRect(hWndStatus, (LPRECT) NULL, TRUE);
  801.       }
  802.       return TRUE;
  803.     }
  804.  
  805.  
  806.     case WM_MDIACTIVATE:
  807.       if (wParam == TRUE)
  808.       {
  809.         /* If we're activating this child, remember it */
  810.         hWndActive = hWnd;
  811.         hCurrStockInfo = GetWindowWord(hWnd, 0);
  812.  
  813.         if ((lpStockInfo = (LPSTOCKINFO) GlobalLock(hCurrStockInfo)))
  814.         {
  815.           if (lpStockInfo->graphAttrs.iMappingMode == MM_ISOTROPIC)
  816.           {
  817.             CheckMenuItem(GetMenu(hWndMain), ID_GRAPH_ISOTROPIC,
  818.                            MF_BYCOMMAND | MF_CHECKED);
  819.             CheckMenuItem(GetMenu(hWndMain), ID_GRAPH_ANISOTROPIC,
  820.                            MF_BYCOMMAND | MF_UNCHECKED);
  821.           }
  822.           else
  823.           {
  824.             CheckMenuItem(GetMenu(hWndMain), ID_GRAPH_ISOTROPIC,
  825.                            MF_BYCOMMAND | MF_UNCHECKED);
  826.             CheckMenuItem(GetMenu(hWndMain), ID_GRAPH_ANISOTROPIC,
  827.                            MF_BYCOMMAND | MF_CHECKED);
  828.           }
  829.           GlobalUnlock(hCurrStockInfo);
  830.         }
  831.       }
  832.  
  833.       break;
  834.  
  835.  
  836.     case WM_PAINT     :
  837.     {
  838.       HDC         hDC;
  839.       PAINTSTRUCT ps;
  840.  
  841.       hDC = BeginPaint(hWnd, (LPPAINTSTRUCT) &ps);
  842.  
  843.       if ((hStockInfo = GetWindowWord(hWnd, 0)) != NULL && 
  844.           (lpStockInfo = (LPSTOCKINFO) GlobalLock(hStockInfo)))
  845.       {
  846.         GraphWndPaint(hWnd, hDC, lpStockInfo, FALSE);
  847.         GlobalUnlock(hStockInfo);
  848.       }
  849.  
  850.       EndPaint(hWnd, &ps);
  851.       break;
  852.     }
  853.  
  854.  
  855.     case WM_QUERYENDSESSION:
  856.     case WM_CLOSE:
  857.       /*
  858.         See if the stock information has been altered during this
  859.         session. If so, prompt the user to see if he really wants
  860.         to close down the stock window.
  861.       */
  862.       if ((hStockInfo = GetWindowWord(hWnd, 0)) != NULL && 
  863.           (lpStockInfo = (LPSTOCKINFO)GlobalLock(hStockInfo))!=NULL)
  864.       {
  865.         if ((lpStockInfo->dwFlags & STATE_DIRTY) && 
  866.              MessageBox(hWndMain, "OK to close window?", "Stock",
  867.                         MB_ICONQUESTION | MB_OKCANCEL) == IDCANCEL)
  868.         {
  869.           GlobalUnlock(hStockInfo);
  870.           return FALSE;
  871.         }
  872.         GlobalUnlock(hStockInfo);
  873.       }
  874.       goto call_DCP;
  875.  
  876.  
  877.     case WM_DESTROY:
  878.       /*
  879.         Free all of the stock information which was allocated for a
  880.         window.
  881.       */
  882.       if ((hStockInfo = GetWindowWord(hWnd, 0)) != NULL && 
  883.           (lpStockInfo = (LPSTOCKINFO) GlobalLock(hStockInfo))!=NULL)
  884.       {
  885.         GlobalFree(lpStockInfo->hTicks);
  886.         GlobalUnlock(hStockInfo);
  887.         GlobalFree(hStockInfo);
  888.         if (hWnd == hWndActive)
  889.         {
  890.           hWndActive = NULL;
  891.           hCurrStockInfo = NULL;
  892.         }
  893.       }
  894.       goto call_DCP;
  895.  
  896.     default:
  897.       /*
  898.         Again, since the MDI default behaviour is a little different,
  899.         call DefMDIChildProc instead of DefWindowProc()
  900.       */
  901. call_DCP:
  902.       return DefMDIChildProc(hWnd, msg, wParam, lParam);
  903.   }
  904.  
  905.   return (LONG) FALSE;
  906. }
  907.  
  908.